package modules.sys.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import luxing.common.controller.BaseController;
import luxing.common.service.SmsService;
import luxing.constant.SmsConfig;
import luxing.exception.BusinessException;
import luxing.util.IpUtil;
import luxing.util.JsonUtil;
import luxing.util.LoginUserUtil;
import luxing.util.RequestUtil;
import luxing.util.SecretUtil;
import luxing.web.model.LoginUser;
import luxing.web.model.Result;
import manage.sys.entity.Menu;
import manage.sys.entity.UserSession;
import manage.sys.service.MenuService;
import manage.sys.service.UserSessionService;
import manage.tenant.entity.Tenant;
import manage.tenant.service.TenantService;
import modules.sys.entity.IndexData;
import modules.sys.entity.Log;
import modules.sys.entity.User;
import modules.sys.entity.UserLogin;
import modules.sys.service.IndexDataService;
import modules.sys.service.LogService;
import modules.sys.service.UserLoginService;
import modules.sys.service.UserService;

/**
 * 登陆
 * 
 * @author Administrator
 *
 */
@Controller
@RequestMapping("/index")
public class IndexController extends BaseController {

	private Logger logger = Logger.getLogger(IndexController.class);

	@Autowired
	private LogService logService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserLoginService userLoginService;
	@Autowired
	private MenuService menuService;
	@Autowired
	private TenantService tenantService;
	@Autowired
	private IndexDataService indexDataService;
	@Autowired
	private SmsService smsService;
	@Autowired
	private UserSessionService userSessionService;

	/**
	 * 用户核对
	 */
	@RequestMapping(params = "check")
	@ResponseBody
	public Result check(User user, HttpServletRequest req) {
		Result result = new Result();
		// IP地址是否被锁定
		List<UserLogin> blackIpList = userLoginService.listByIP(IpUtil.getIpAddr(req));
		if (CollectionUtils.isNotEmpty(blackIpList)) {
			return Result.error("该地址已被锁定");
		}
		// 账号是否锁定
		UserLogin userLogin = userLoginService.getByPhone(user.getPhone());
		if (userLogin != null && userLogin.getLoginNum() >= 10) {
			logger.error("用户:" + user.getName() + ",已锁定");
			return Result.error("账号被锁定24小时,请联系公司管理员!");
		}
		// 用户登录验证逻辑
		User userdb = null;
		try {
			userdb = userService.loginCheck(user);
		} catch (Exception e) {
			logger.error("登陆失败", e);
			return Result.error("登陆失败");
		}
		if (userdb == null) {
			// 登录失败记录
			if (userLogin == null) {
				userLogin = new UserLogin();
			}
			userLogin.setPhone(user.getPhone());
			userLogin.setIp(IpUtil.getIpAddr(req));
			if (userLogin.getLoginNum() == null) {
				userLogin.setLoginNum(0);
			}
			userLogin.setLoginNum(userLogin.getLoginNum() + 1);
			userLoginService.saveOrUpdate(userLogin);
			logger.error("用户:" + user.getPhone() + ",登录失败");
			return Result.error("手机或密码错误");
		} else {
			// 一个用户属于多个租户
			Map<String, Object> attributes = new HashMap<String, Object>();
			String tenantId = req.getParameter("tenantId");
			if (StringUtils.isNotBlank(tenantId)) {
				// 判断租户状态
				Tenant tenant = tenantService.get(Tenant.class, tenantId);
				if (tenant.getStatus().equals(Tenant.STATUS_DISABLE)) {
					return Result.error("账号已欠费停用");
				}
				// 如果租户不为空,保存登录信息
				attributes.put("tenantNum", 1);
				saveLoginInfo(req, userdb, tenantId);
			} else {
				if (userdb.getTenantList().size() == 1) {
					// 只属于一个租户
					attributes.put("tenantNum", 1);
					// 判断租户状态
					Tenant tenant = tenantService.get(Tenant.class, userdb.getTenantList().get(0).getId());
					if (tenant.getStatus().equals(Tenant.STATUS_DISABLE)) {
						return Result.error("账号已欠费停用");
					}
					saveLoginInfo(req, userdb, userdb.getTenantList().get(0).getId());
				} else if (userdb.getTenantList().size() > 1) {
					// 如果属于多个租户
					attributes.put("tenantNum", userdb.getTenantList().size());
					attributes.put("userId", userdb.getId());
				}
			}
			result.setAttributes(attributes);
			result.setMsg("登录成功");
		}
		return result;
	}

	/**
	 * 保存用户登录的信息，
	 * 
	 * @param req
	 *            request
	 * @param user
	 *            当前登录用户
	 */
	private void saveLoginInfo(HttpServletRequest req, User user, String tenantId) {
		HttpSession session = RequestUtil.getSession();
		// 当前session为空 或者 当前session的用户信息与刚输入的用户信息一致时，则更新Client信息
		User sessionUser = LoginUserUtil.getUser();
		if (sessionUser == null || (sessionUser.getId().equals(user.getId()))) {
			LoginUser loginUser = new LoginUser();
			loginUser.setIp(IpUtil.getIpAddr(req));
			loginUser.setLoginTime(new Date());
			loginUser.setUser(user);
			loginUser.setTenantId(tenantId);
			LoginUserUtil.addLoginUser(session.getId(), loginUser);
			// 记录用户sessionId,只允许用户在一处登录
			UserSession userSession = userSessionService.getByUser(user.getId());
			if (userSession != null) {
				userSession.setSessionId(session.getId());
				userSessionService.update(userSession);
			} else {
				userSession = new UserSession();
				userSession.setUserId(user.getId());
				userSession.setSessionId(session.getId());
				userSessionService.save(userSession);
			}
		} else {
			// 如果不一致，则注销session并通过session=req.getSession(true)初始化session
			LoginUserUtil.removeLoginUser(session.getId());
			session.invalidate();
			// session初始化
			session = req.getSession(true);
			// 用户核对
			check(user, req);
		}
		// 添加登陆日志
		logger.info("用户:" + user.getName() + ",登陆成功");
		logService.addLogInfo("用户:" + user.getName() + ",登陆成功", Log.OPERATE_LOGIN);
	}

	/**
	 * 租户选择
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "goTenantSelect")
	public ModelAndView goTenantSelect(HttpServletRequest request) {
		String userId = request.getParameter("userId");
		User user = userService.get(User.class, userId);
		request.setAttribute("userId", user.getId());
		request.setAttribute("userName", user.getName());
		request.setAttribute("tenantList", user.getTenantList());
		return new ModelAndView("login/tenant-select");
	}

	/**
	 * 租户选择
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "doTenantSelect")
	@ResponseBody
	public Result doTenantSelect(HttpServletRequest request) {
		String userId = request.getParameter("userId");
		User user = userService.get(User.class, userId);
		saveLoginInfo(request, user, request.getParameter("tenantId"));
		return Result.success("用户登录成功");
	}

	/**
	 * 后台页面
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "main")
	public String main(HttpServletRequest request, HttpServletResponse response) {
		User user = LoginUserUtil.getUser();
		if (user != null) {
			Tenant tenant = tenantService.get(Tenant.class, LoginUserUtil.getLoginUser().getTenantId());
			request.setAttribute("balance", tenant.getBalance());
			request.setAttribute("tenantName", tenant.getName());
			request.setAttribute("userName", user.getName());
			request.setAttribute("userMenu", getUserMenu(user));
			Cookie zIndexCookie = new Cookie("ZINDEXNUMBER", "1990");
			zIndexCookie.setMaxAge(3600 * 24);// 一天
			response.addCookie(zIndexCookie);
			return "main/main";
		} else {
			return "login/login";
		}
	}

	/**
	 * 获取权限的map
	 * 
	 * @param user
	 * @return
	 */
	private Map<Integer, List<Menu>> getUserMenu(User user) {
		LoginUser loginUser = LoginUserUtil.getLoginUser();
		if (loginUser.getUserMenu() == null) {
			Map<Integer, List<Menu>> userMenu = menuService.mapLevelMenuByUser(user.getId());
			loginUser.setUserMenu(userMenu);
			return userMenu;
		} else {
			return loginUser.getUserMenu();
		}
	}

	/**
	 * 主页
	 *
	 * @return
	 */
	@RequestMapping(params = "home")
	public ModelAndView home(HttpServletRequest request) {
		List<IndexData> indexDataList = indexDataService.listByType(IndexData.TYPE_CLDT);
		Map<String, Integer> cldtMap = new HashMap<String, Integer>();
		for (IndexData indexData : indexDataList) {
			cldtMap.put(indexData.getName(), indexData.getValue());
		}
		request.setAttribute("cldtMap", cldtMap);
		return new ModelAndView("main/home");
	}

	/**
	 * 车辆状态数据
	 * 
	 * @param req
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(params = "statusChart")
	@ResponseBody
	public Result statusChart(HttpServletRequest req) {
		Result result = new Result();
		Map<String, Object> attributes = new HashMap<String, Object>();
		List<IndexData> indexDataList = indexDataService.listByType(IndexData.TYPE_CLZT);
		List<String> legend = new ArrayList<String>();
		List<Map> serisData = new ArrayList<Map>();
		for (IndexData indexDataEntity : indexDataList) {
			legend.add(indexDataEntity.getName());
			Map map = new HashMap();
			map.put("value", indexDataEntity.getValue());
			map.put("name", indexDataEntity.getName());
			serisData.add(map);
		}
		attributes.put("legend", legend);
		attributes.put("serisData", serisData);
		result.setAttributes(attributes);
		return result;
	}

	/**
	 * 到期提醒数据
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping(params = "warnChart")
	@ResponseBody
	public Result warnChart(HttpServletRequest req) {
		String warnDayType = req.getParameter("warnDayType");
		warnDayType = StringUtils.isBlank(warnDayType) ? IndexData.TYPE_TX10 : warnDayType;
		Result result = new Result();
		Map<String, Object> attributes = new HashMap<String, Object>();
		List<IndexData> indexDataList = indexDataService.listByType(warnDayType);
		List<String> categories = new ArrayList<String>();
		List<Integer> series = new ArrayList<Integer>();
		for (IndexData indexDataEntity : indexDataList) {
			categories.add(indexDataEntity.getName());
			series.add(indexDataEntity.getValue());
		}
		attributes.put("categories", categories);
		attributes.put("series", series);
		result.setAttributes(attributes);
		return result;
	}

	/**
	 * 登录
	 *
	 * @return
	 */
	@RequestMapping(params = "login")
	public ModelAndView login(HttpServletRequest request) {
		return new ModelAndView("login/login");
	}

	/**
	 * 重置密码
	 *
	 * @return
	 */
	@RequestMapping(params = "passwordReset")
	public ModelAndView passwordReset(HttpServletRequest request) {
		return new ModelAndView("login/password-reset");
	}

	/**
	 * 退出系统
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "logout")
	public ModelAndView logout(HttpServletRequest request) {
		HttpSession session = RequestUtil.getSession();
		User user = LoginUserUtil.getUser();
		logService.addLogInfo("用户:" + user.getName() + ",退出", Log.OPERATE_EXIT);
		LoginUserUtil.removeLoginUser(session.getId());
		session.invalidate();
		ModelAndView modelAndView = new ModelAndView(new RedirectView("index.do?login"));
		return modelAndView;
	}

	/**
	 * 短信发送校验
	 * 
	 * @param user
	 * @param req
	 * @return
	 */
	@RequestMapping(params = "sendSmsCheck")
	@ResponseBody
	public Result sendSmsCheck(String phone, HttpServletRequest req) {
		Result result = new Result();
		HttpSession session = req.getSession();
		// 手机号是否已注册
		if (userService.getByPhone(phone) == null) {
			return Result.error("手机号码尚未注册");
		}
		// 验证码是否正确
		String randCode = req.getParameter("randCode");
		if (StringUtils.isBlank(randCode) || !randCode.equalsIgnoreCase((String) session.getAttribute("randCode"))) {
			return Result.error("图形验证码错误");
		}
		return result;
	}

	/**
	 * 发送密码重置短信
	 * 
	 * @param phone
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "sendSms")
	@ResponseBody
	public Result sendSms(String phone, HttpServletRequest request) {
		String msg = null;
		try {
			User user = userService.getByPhone(phone);
			if (user == null) {
				return Result.error("用户不存在，短信发送失败");
			}
			Tenant tenant = user.getTenantList().get(0);
			// 判断用户余额
			if (tenant.getBalance().compareTo(Tenant.BALANCE_MIN) < 0) {
				msg = "账户余额不足,发送失败.";
				return Result.error(msg);
			}
			// 生成短信验证码
			String code = String.valueOf(new Random().nextInt(899999) + 100000);
			request.getSession().setAttribute(phone + SmsConfig.key_password_reset, code);
			Map<String, String> paramMap = new HashMap<String, String>();
			paramMap.put("code", code);
			String templateParam = JsonUtil.toJson(paramMap);
			// 发送短信
			smsService.sendSms(phone, SmsConfig.template_password_reset, templateParam, tenant, user);
			msg = "短信发送成功";
			logger.info(msg);
		} catch (Exception e) {
			msg = "短信发送失败";
			logger.error(msg, e);
			throw new BusinessException(msg, e);
		}
		return Result.success(msg);
	}

	/**
	 * 发送密码重置短信
	 * 
	 * @param phone
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "doPassword")
	@ResponseBody
	public Result doPassword(User user, HttpServletRequest request) {
		String msg = null;
		try {
			// 是否为弱密码
			if (SecretUtil.weakPassword(user.getPassword())) {
				return Result.error("密码太简单");
			}
			// 短信验证码是否正确
			String smsCode = request.getParameter("smsCode");
			if (StringUtils.isBlank(smsCode) || !smsCode.equalsIgnoreCase(
					(String) request.getSession().getAttribute(user.getPhone() + SmsConfig.key_password_reset))) {
				return Result.error("短信验证码错误");
			}
			// 修改用户密码
			User userDB = userService.getByPhone(user.getPhone());
			if (userDB == null) {
				return Result.error("用户不存在，密码修改失败");
			}
			userDB.setPassword(SecretUtil.encrypt(user.getPhone(), user.getPassword(), SecretUtil.getStaticSalt()));
			userService.updatePassword(userDB);
			msg = "密码修改成功";
			logger.info(msg);
		} catch (Exception e) {
			msg = "密码修改失败";
			logger.error(msg, e);
			throw new BusinessException(msg, e);
		}
		return Result.success(msg);
	}

	/**
	 * 帮助页面
	 * 
	 * @return
	 */
	@RequestMapping(params = "goHelp")
	public ModelAndView goHelp(HttpServletRequest req) {
		return new ModelAndView("modules/sys/help");
	}

	/**
	 * 充值页面
	 *
	 * @return
	 */
	@RequestMapping(params = "goHelp")
	public ModelAndView goRecharge(HttpServletRequest req) {
		return new ModelAndView("modules/sys/recharge");
	}

}